 package com.gmrz.uaf.crypto;

 import com.gmrz.uaf.crypto.internal.algos.UAFAuthAlg;
 import com.gmrz.uaf.crypto.internal.algos.UAFAuthAlgECDSARaw;
 import com.gmrz.uaf.crypto.internal.algos.UAFAuthAlgRSADer;
 import com.gmrz.uaf.crypto.internal.algos.UAFAuthAlgSM2;
 import com.gmrz.uaf.crypto.internal.handlers.*;
 import com.gmrz.uaf.crypto.internal.keyFormats.UAFAlgKeyECCX962Raw;
 import com.gmrz.uaf.crypto.internal.keyFormats.UAFAlgKeyRSA2048PSSDer;
 import com.gmrz.uaf.crypto.internal.keyFormats.UAFAlgKeyRSA2048PSSRaw;
 import com.gmrz.uaf.crypto.internal.keyFormats.UAFKeyFmt;
 import com.gmrz.uaf.crypto.spi.CryptoService;
 import com.gmrz.uaf.crypto.spi.UAFAuthAlgorithmSuite;
 import com.gmrz.uaf.crypto.spi.UAFKeyFormat;
 import com.gmrz.uaf.crypto.spi.handlers.*;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;

 import java.security.GeneralSecurityException;
 import java.util.*;
 
 public class DefaultCryptoService implements CryptoService
 {
   private static final Logger LOG = LogManager.getLogger(DefaultCryptoService.class);
 
   private List<String> defaultOperationsToBeLoaded = null;
   private CryptoConfig cryptoConfig = null;
 
   public DefaultCryptoService(List<String> defaultOperationsToBeLoaded, CryptoConfig cryptoConfig) {
     this.defaultOperationsToBeLoaded = defaultOperationsToBeLoaded;
     this.cryptoConfig = cryptoConfig;
   }
 
   public void initialize(Properties props)
     throws GeneralSecurityException
   {
   }
 
   public List<UAFAuthAlgorithmSuite> getSupportedAlgos()
   {
     List<UAFAuthAlgorithmSuite> defaultAlgos = new ArrayList<UAFAuthAlgorithmSuite>();
 
     defaultAlgos.add(new UAFAuthAlgECDSARaw(CryptoConstants.UAFAlgSign.UAF_ALG_SIGN_SECP256R1_ECDSA_SHA256_RAW));
 
     defaultAlgos.add(new UAFAuthAlg(CryptoConstants.UAFAlgSign.UAF_ALG_SIGN_SECP256R1_ECDSA_SHA256_DER));
 
     defaultAlgos.add(new UAFAuthAlg(CryptoConstants.UAFAlgSign.UAF_ALG_SIGN_RSASSA_PSS_SHA256_RAW));
 
     defaultAlgos.add(new UAFAuthAlgRSADer(CryptoConstants.UAFAlgSign.UAF_ALG_SIGN_RSASSA_PSS_SHA256_DER));
 
     defaultAlgos.add(new UAFAuthAlgECDSARaw(CryptoConstants.UAFAlgSign.UAF_ALG_SIGN_SECP256K1_ECDSA_SHA256_RAW));
 
     defaultAlgos.add(new UAFAuthAlg(CryptoConstants.UAFAlgSign.UAF_ALG_SIGN_SECP256K1_ECDSA_SHA256_DER));
 
     defaultAlgos.add(new UAFAuthAlg(CryptoConstants.UAFAlgSign.UAF_ALG_SIGN_RSASSA_PKCS1_SHA256_RAW));
 
     defaultAlgos.add(new UAFAuthAlgRSADer(CryptoConstants.UAFAlgSign.UAF_ALG_SIGN_RSASSA_PKCS1_SHA256_DER));

     defaultAlgos.add(new UAFAuthAlgSM2(CryptoConstants.UAFAlgSign.UAF_ALG_SIGN_SM2));

     defaultAlgos.add(new UAFAuthAlg(CryptoConstants.UAFAlgSign.UAF_ALG_SIGN_RSA));

     return defaultAlgos;
   }
 
   public List<UAFKeyFormat> getSupportedKeyFormats()
   {
     List<UAFKeyFormat> defaultKeyFormats = new ArrayList<UAFKeyFormat>();
     defaultKeyFormats.add(new UAFAlgKeyECCX962Raw());
     defaultKeyFormats.add(new UAFKeyFmt(CryptoConstants.UAFAlgkey.UAF_ALG_KEY_ECC_X962_DER));
     defaultKeyFormats.add(new UAFAlgKeyRSA2048PSSDer());
     defaultKeyFormats.add(new UAFAlgKeyRSA2048PSSRaw());
     return defaultKeyFormats;
   }
 
   public AttestationCertHandler getAttestationCertHandler()
   {
     return new X509AttestationCertHandler();
   }
 
   public Map<String, CipherHandler> getCipherHandlers()
   {
     Map<String, CipherHandler> cipherHandlers = new HashMap<String, CipherHandler>();
     if (this.defaultOperationsToBeLoaded.contains(Operations.SERVER_DATA_CIPHER)) {
       LOG.info("Instantiating default CipherHandler implementation for operation - " + Operations.SERVER_DATA_CIPHER);
       cipherHandlers.put(Operations.SERVER_DATA_CIPHER, new ServerDataCipherHandler(this.cryptoConfig));
     }
     if (this.defaultOperationsToBeLoaded.contains(Operations.PASSWORD_CIPHER)) {
       LOG.info("Instantiating default CipherHandler implementation for operation - " + Operations.PASSWORD_CIPHER);
       cipherHandlers.put(Operations.PASSWORD_CIPHER, new PasswordCipherHandler());
     }
 
     return cipherHandlers;
   }
 
   public Map<String, HashHandler> getHashHandlers()
   {
     Map<String,HashHandler> hashHandlers = new HashMap<String,HashHandler>();
     if (this.defaultOperationsToBeLoaded.contains(Operations.DATA_HASH)) {
       LOG.info("Instantiating default data hash implementation for operation - " + Operations.DATA_HASH);
       hashHandlers.put(Operations.DATA_HASH, new DefaultHashHandler());
     }
     return hashHandlers;
   }
 
   public Map<String, HMACHandler> getHMACHandlers()
   {
     Map<String,HMACHandler> hmacHandlers = new HashMap<String,HMACHandler>();
     if (this.defaultOperationsToBeLoaded.contains(Operations.HMAC)) {
       LOG.info("Instantiating default HMAC implementation for operation - " + Operations.HMAC);
       hmacHandlers.put(Operations.HMAC, new DefaultHMACHandler(this.cryptoConfig));
     }
     return hmacHandlers;
   }
 }
